package com.system.comm.utils;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.beans.BeanMap;

import com.system.comm.model.ContrastBean;

/**
 * 实体的工具类<br>
 * @author yuejing
 * @date 2017年1月23日 下午3:07:40
 * @version V1.0.0
 */
public class FrameBeanUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(FrameBeanUtil.class);

	/**
	 * 得到值相同的属性[类必须相同]<br>
	 * 注意：bean里面的类属性是不能比较的
	 * @param obj1
	 * @param obj2
	 * @return
	 */
	public static List<ContrastBean> contrastEqual(Object obj1, Object obj2) {
		List<ContrastBean> list = new ArrayList<ContrastBean>();
		try {
			Class<?> clazz = obj1.getClass();
			Field[] fields = obj1.getClass().getDeclaredFields();
			for (Field field : fields) {
				field.setAccessible(true);
				PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
				Method getMethod = pd.getReadMethod();
				getMethod.setAccessible(true);
				Object o1 = getMethod.invoke(obj1);
				Object o2 = getMethod.invoke(obj2);
				if (o1.toString().equals(o2.toString())) {
					list.add(new ContrastBean(field.getName(), o1, o2));
				}
			}
		} catch (Exception e) {
			LOGGER.error("对比异常: " + e.getMessage(), e);
		}
		return list;
	}
	/**
	 * 得到值不同的属性[类必须相同]<br>
	 * 注意：bean里面的类属性是不能比较的
	 * @param obj1
	 * @param obj2
	 * @return
	 */
	public static List<ContrastBean> contrastDiff(Object obj1, Object obj2) {
		List<ContrastBean> list = new ArrayList<ContrastBean>();
		try {
			Class<?> clazz = obj1.getClass();
			Field[] fields = obj1.getClass().getDeclaredFields();
			for (Field field : fields) {
				field.setAccessible(true);
				PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
				Method getMethod = pd.getReadMethod();
				getMethod.setAccessible(true);
				Object o1 = getMethod.invoke(obj1);
				Object o2 = getMethod.invoke(obj2);
				boolean bool1 = (o1 == null && o2 != null);
				boolean bool2 = bool1 ? true : (o2 == null && o1 != null);
				boolean bool3 = bool2 ? true : (o1 != null && o2 != null && !o1.toString().equals(o2.toString()));
				if ( bool1
						|| bool2
						|| bool3) {
					list.add(new ContrastBean(field.getName(), o1, o2));
				}
			}
		} catch (Exception e) {
			LOGGER.error("对比异常: " + e.getMessage(), e);
		}
		return list;
	}
	/**
	 * 对象转Map
	 * @param object
	 * @return
	 */
	public static Map<String, Object> toMap(Object object) {
		/*String string = FrameJsonUtil.toString(object);
		return FrameJsonUtil.toMap(string);*/

		Map<String, Object> map = new HashMap<>();
		if (object != null) {
			BeanMap beanMap = BeanMap.create(object);
			for (Object key : beanMap.keySet()) {
				if (key != null) {
					Object value = beanMap.get(key);
					if (value != null) {
						if (value instanceof Date) {
							map.put(key.toString(), FrameTimeUtil.parseString((Date) value));
						} else {
							map.put(key.toString(), value);
						}
					}
				}
			}
		}
		return map;
	}
	/**
	 * 对象转Map
	 * @param clazz
	 * @return 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T toBean(Map<String, Object> map, Class<?> clazz) {
		T bean = null;
		try {
			bean = (T) clazz.newInstance();
			BeanMap beanMap = BeanMap.create(bean);
			Iterator<String> keys = map.keySet().iterator();
			String key = null;
			while(keys.hasNext()) {
				key = keys.next();
				Class<?> propertyType = beanMap.getPropertyType(key);
				if (Long.class.equals(propertyType)) {
					// 为Integer类型
					Object value = map.get(key);
					if (value != null) {
						if (value instanceof Integer) {
							// 实体属性为Long
							map.put(key, new Long(value.toString()));
						}
					}
				} else if (Date.class.equals(propertyType)) {
					// 为日期类型
					Object value = map.get(key);
					if (value != null) {
						String valueString = value.toString();
						if (!"".equals(valueString)) {
							if (valueString.length() == 10) {
								map.put(key, FrameTimeUtil.parseDate(valueString, FrameTimeUtil.FMT_YYYY_MM_DD));
							} else {
								map.put(key, FrameTimeUtil.parseDate(valueString));
							}
						}
					}
				} else if (List.class.equals(propertyType)) {
					// 为List
					Object values = map.get(key);
					if (values != null) {
						List<Object> valueList = (List<Object>) values;
						if (valueList.size() > 0) {
							// 存在值并且值类型为Map
							if (valueList.get(0) instanceof Map) {
								// 得到List的属性的Class
								Class<?> valueClazz = getListValueClass(key, clazz);
								if (valueClazz != null && !Map.class.equals(valueClazz)) {
									// valueClazz不为空，并且不为Map，则转换为对应的List对象
									List<Object> currentValueList = new ArrayList<>();
									for (Object object : valueList) {
										Map<String, Object> classMap = (Map<String, Object>) object;
										currentValueList.add(toBean(classMap, valueClazz));
									}
									map.put(key, currentValueList);
								}
							}

						}
					}
				}
			}
			beanMap.putAll(map);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bean;
	}

	/**
	 * 将List<T>转换为List<Map<String, Object>>
	 * 
	 * @param objList
	 * @return
	 */
	public static <T> List<Map<String, Object>> toMaps(List<T> objList) {
		List<Map<String, Object>> list = new ArrayList<>();
		if (objList != null && objList.size() > 0) {
			Map<String, Object> map = null;
			T bean = null;
			for (int i = 0, size = objList.size(); i < size; i++) {
				bean = objList.get(i);
				map = toMap(bean);
				list.add(map);
			}
		}
		return list;
	}

	/**
	 * 将List<Map<String,Object>>转换为List<T>
	 * 
	 * @param maps
	 * @param clazz
	 * @return
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public static <T> List<T> toBeans(List<Map<String, Object>> maps, Class<T> clazz) {
		List<T> list = new ArrayList<>();
		if (maps != null && maps.size() > 0) {
			Map<String, Object> map = null;
			T bean = null;
			for (int i = 0, size = maps.size(); i < size; i++) {
				map = maps.get(i);
				bean = toBean(map, clazz);
				list.add(bean);
			}
		}
		return list;
	}

	/**
	 * 获取List的属性的类型
	 * @param key
	 * @param clazz
	 * @return
	 * @throws IntrospectionException 
	 */
	private static Class<?> getListValueClass(String key, Class<?> clazz) throws IntrospectionException {
		Class<?> valueClazz = null;
		PropertyDescriptor[] props = Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors();
		if (props != null) {
			for (int i = 0; i < props.length; i++) {
				//获取bean中的属性
				String propName = props[i].getName();
				if (propName.equals(key)) {
					PropertyDescriptor pd = props[i];
					Method m = pd.getReadMethod();
					ParameterizedType pt = (ParameterizedType) m.getGenericReturnType();
					Type vct = pt.getActualTypeArguments()[0];
					if (!"T".equals(vct.getTypeName())) {
						valueClazz = (Class<?>) pt.getActualTypeArguments()[0];
					}
				}
			}
		}
		return valueClazz;
	}

	/*public static void main(String[] args) {
		Orderby obj1 = new Orderby("sdf", "asc", 0);
		Orderby obj2 = new Orderby("sdf", "asc", 1);
		List<ContrastBean> list = contrastDiff(obj1, obj2);
		for (ContrastBean cb : list) {
			System.out.println(cb.getProperty() + "||" + cb.getValue1() + "||" + cb.getValue2());
		}
	}*/
}